<!--
 * @Author: pmy
 * @Date: 2021-09-02 14:39:12
 * @LastEditTime: 2022-11-25 09:57:21
 * @LastEditors: pmy
 * @Description: 双查询页面
 * @FilePath: \bdcar-net\src\components\table\baseTable.vue
-->

<template>
  <div class="tablePage" v-loading="loading">
    <div class="search">
      <!-- 查询条件select类 -->
      <div class="header-query" v-for="v in queryArr" :key="v.prop"
        v-show="v.show == true || v.show == query.predictObj">
        <span class="search-text">{{ v.name }}</span>
        <template v-if="v.type == 'select'">
          <el-select v-model="query[v.prop]" :placeholder="v.placeholder" filterable class="search-input">
            <el-option v-for="vv in optionList[v.prop]" :key="vv.value" :label="vv.label" :value="vv.value">
            </el-option>
          </el-select>
        </template>
        <!-- 查询条件input类 -->
        <template v-else-if="v.type == 'input'">
          <el-input clearable v-model="query[v.prop]" :placeholder="v.placeholder" class="search-input"
            @change="pagination.currentPage = 1;"
            @keyup.native.enter="pagination.currentPage = 1; getTableData()"></el-input>
        </template>
        <!-- 查询条件cascader类 -->
        <template v-else-if="v.type == 'cascader'">
          <el-cascader v-model="query[v.prop]" class="search-input" :placeholder="v.placeholder"
            :options="optionList[v.prop]" :props="cascaderSet" @change="pagination.currentPage = 1; getTableData()"
            :clearable="false"></el-cascader>
        </template>
        <!-- 查询条件time类 -->
        <template v-else-if="v.type == 'year'">
          <el-date-picker v-model="query[v.prop]" :type="'year'" class="search-input time-picker" :format="'yyyy'"
            :value-format="'yyyy'">
          </el-date-picker>
        </template>
        <!-- 查询条件DateTime类 -->
        <template v-else-if="v.type == 'dateTime'">
          <el-date-picker v-model="query[v.prop]" :type="'datetimerange'" range-separator="至"
            :start-placeholder="v.placeholder[0]" :clearable="false" :end-placeholder="v.placeholder[1]"
            :picker-options="pickerOptions" class="search-input dateTime-picker" :format="'yyyy-MM-dd HH:mm:ss'"
            :value-format="'yyyy-MM-dd HH:mm:ss'">
          </el-date-picker>
        </template>
        <!-- 查询条件Monthe类 -->
        <template v-else-if="v.type == 'month'">
          <el-date-picker v-model="query[v.prop]" type="month" class="search-input time-picker" format="yyyy-MM"
            value-format="yyyy-MM">
          </el-date-picker>
        </template>
      </div>

      <div class="search-btn" @click="getTableData()" v-if="Btn.search">
        <div class="btn-img"></div>查询
      </div>
      <div class="add-btn" @click="handleClick(null, 'add')" v-if="Btn.add"
        v-show="btnPermissionSearch('basicData', 'fileManage', 'add')">
        <div class="btn-img"></div>新增
      </div>
      <div class="export-btn" @click="handleClick(null, 'export')" v-if="Btn.export" v-loading="exportLoading">
        <div class="btn-img"></div>
        {{ !exportLoading ? "导出" : "导出中" }}
      </div>
      <div class="deletes-btn" @click="handleClick(null, 'deletes')" v-if="Btn.deletes"
        v-show="btnPermissionSearch('basicData', 'fileManage', 'deletes')">
        批量删除
      </div>
    </div>
    <div class="split-line"></div>
    <div class="base-table">
      <ul v-for="v in tableAllData?.returnfrontdf">
        <li v-for="(val, key) in v">
          <!-- <span>推广浏览转化率预测值：</span> -->
          <span>{{ myDict[key] }}：</span>
          <el-input v-model="v[key]" class="edit-input" :placeholder="placeholderDict[key]?placeholderDict[key]:'请输入'" :disabled="!queryDict[key]"></el-input>
        </li>
      </ul>
    </div>
    <div class="split-line"></div>
    <div class="predict-btn" @click="start2Predict">开始预测</div>
  </div>
</template>

<script>
import treeSelect from "@/components/common/treeSelect"
import { service } from "../../services/backServices"
import FileControl from '@/components/common/FileControl.vue';
import { saveAs } from "file-saver";
import { export_json_to_excel } from "@/assets/js/FilExport";
import dayjs from "dayjs";
export default {
  props: [
    "queryArr",//查询参数
    "tableItems",//表格表头
    "updateItems",//增删查改的对象属性
    "optionList",//增删查改的对象属性的下拉select或者级联casual
    "methodParam",//方法参数
    "methodParam2",
    "Btn",//自定义btn功能
    "menuName",//权限-菜单名称
    "pageName",//权限-页面名称
    "baseDict",//字典
    "queryDict",//第二阶段查询时的参数列表
    "placeholderDict"
  ],
  components: { treeSelect, FileControl },
  data() {
    return {
      uploading: false,
      exportLoading: false,
      loading: false,
      method: {},
      //表格参数
      pagination: {
        total: 0,
        currentPage: 1,
        pageSize: 50,
      },
      multipleSelection: [],
      tableData: [],
      showWhich: "",
      updateInfo: {
        fileName: ''
      },
      params: {},
      cascaderSet: {
        value: 'value',
        emitPath: false,
        checkStrictly: false,
        expandTrigger: 'hover',
        multiple: false
      },
      addformRules: {
        fileName: [
          { required: true, message: '文件名称', trigger: 'blur' },
        ],
        fileAdd: [
          { required: true, message: '上传文件', trigger: 'blur' },
        ],
        uploadType: [
          { required: true, message: '上传类型', trigger: 'change' },
        ]
      },
      pickerOptions: {
        shortcuts: [
          {
            text: "最近一天",
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 1);
              picker.$emit("pick", [start, end]);
            },
          },
          {
            text: "最近两天",
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 2);
              picker.$emit("pick", [start, end]);
            },
          },
          {
            text: "最近三天",
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 3);
              picker.$emit("pick", [start, end]);
            },
          }
        ],
        disabledDate: (time) => {
          return time.getTime() > Date.now() - 8.64e7;
        },
      },
      pickerOptionsMonth: {
        shortcuts: [{
          text: '本月',
          onClick(picker) {
            picker.$emit('pick', [new Date(), new Date()]);
          }
        }, {
          text: '今年至今',
          onClick(picker) {
            const end = new Date();
            const start = new Date(new Date().getFullYear(), 0);
            picker.$emit('pick', [start, end]);
          }
        }, {
          text: '最近六个月',
          onClick(picker) {
            const end = new Date();
            const start = new Date();
            start.setMonth(start.getMonth() - 6);
            picker.$emit('pick', [start, end]);
          }
        }]
      },
      dialogTitle: {
        add: "新增",
        edit: "编辑",
        detail: "详情"
      },
      showDialog: false,
      tableAllData: {},
      query: {},
      myDict: {}
    };
  },
  computed: {
    ImportAPI() {
      return GlobalSetting.IotConfig.ftpAPIService;
    },
  },
  created() {
    let _this = this;
    function getParam(query) {
      let myForm = new FormData()
      Object.keys(query).forEach((key) => {
        if (Array.isArray(query[key]) && key.search(/[Tt]ime/) !== -1) {
          myForm.append('beginDate', query[key].length ? query[key][0] : '')
          myForm.append('endDate', query[key].length ? query[key][1] : '')
        } else if (query[key] !== "") {
          myForm.append(key, query[key])
        }
      })
      return myForm
    };
    _this.method.readBlobAsJson = function (blob) {
      return new Promise((resolve, reject) => {
        const reader = new FileReader();

        reader.onload = () => {
          try {
            const json = JSON.parse(reader.result);
            resolve(json);
          } catch (error) {
            reject(error);
          }
        };

        reader.onerror = () => {
          reject(new Error('Failed to read the blob.'));
        };

        reader.readAsText(blob);
      });
    }
    _this.method.getData = async function (query) {
      let url = _this.methodParam;
      return service({
        url: url,
        method: "post",
        data: getParam(query)
      });
    };
    _this.method.addData = async function (model) {
      return service({
        headers: {
          'Content-Type': 'application/json'
        },
        method: 'post',
        url: _this.methodParam + "/save",
        data: model,
      });
    };
    _this.method.editData = async function (model) {
      return service({
        headers: {
          'Content-Type': 'application/json'
        },
        method: 'post',
        url: _this.methodParam + "/update",
        data: model,
      });
    };
    _this.method.deleteData = async function (id) {
      let url = _this.methodParam + "/remove";
      return service({
        method: 'post',
        url: url,
        params: {
          id: id
        },
      });
    };
    _this.method.deleteDatas = async function (ids) {
      return service({
        method: 'post',
        url: _this.methodParam + "/batchRemove",
        params: {
          ids: ids
        },
        paramsSerializer: params => {
          return qs.stringify(params, {
            indices: false
          })
        }
      });
    };
    _this.method.uploadData = async function (data) {
      return service({
        headers: {
          'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundaryqs8javp5GsOgKvoQ'
        },
        method: 'post',
        url: _this.methodParam + "/upload",
        data: data,
        params: {
          uploadType: _this.updateInfo.uploadType
        }
      });
    };
    _this.method.downloadMethod = async function (url) {
      return service({
        method: 'post',
        url: _this.methodParam + "/download",
        responseType: 'blob',
        data: {
          url: url
        },
      });
    };
    _this.queryArr.forEach(v => {
      this.$set(this.query, v.prop, v.value)
    })
    _this.baseDict.forEach(v => {
      _this.myDict[v.prop] = v.name
    })
  },
  mounted() {
    this.getTableData();
  },
  methods: {
    start2Predict() {
      let _params = {}
      _params["returnfrontdf"] = this.tableAllData.returnfrontdf.map(x => {
        let r = {};
        for (let key in x) {
          if (this.queryDict[key]) {
            r[key] = x[key]
          }
        }
        return r;
      });
      _params["usedf"] = this.tableAllData.usedf
      service({
        url: this.methodParam2,
        method: "post",
        responseType: 'blob',
        data: _params
      }).then(res => {
        console.log(res)
        if (res.data.type == 'application/json') {
          this.method.readBlobAsJson(res.data).then(json => {
            this.$notify({
              message: json.msg ? ('数据生成失败：' + json.msg) : '数据生成失败',
              type: "error",
              position: "bottom-right",
              duration: 2000,
            });
          }
          ).catch(err => {
            console.error(err)
          })
        } else if (res.data.type == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') {
          let filename = res.config.url.split('/')[1];
          saveAs(res.data, filename);
        }
      });
    },
    getTableData() {
      this.loading = true
      this.method.getData(this.query).then(response => {
        this.loading = false
        if (response.data.code == 200) {
          response.data.data.returnfrontdf = response.data.data.returnfrontdf.map(
            x => {
              return Object.assign(x, this.queryDict)
            }
          )
          this.tableAllData = response.data.data;
        } else {
          if (this.tableAllData?.returnfrontdf?.length) {
            this.tableAllData?.returnfrontdf.forEach(x => {
              for (let key in x) {
                x[key] = ''
              }
            })
          }
          if (this.tableAllData?.usedf?.length) {
            this.tableAllData.usedf.forEach(x => {
              for (let key in x) {
                x[key] = ''
              }
            })
          }
        }
        console.log(this.tableAllData)
      })
    },
    handleSelectionChange(val) {
      this.multipleSelection = [];
      val.forEach(v => {
        this.multipleSelection.push(v.id);
      })
    },
    getFileName(val) {
      let title = ''
      if (val && val.length > 0) {
        for (let i = 0; i < val.length - 1; i++) {
          title += val[i]
        }
      } else {
        title = ''
      }
      this.updateInfo.fileName = title
      this.$forceUpdate();
    },
    // 增删改查
    handleClick(row, obj) {
      if (this.uploading) {
        this.$message({
          message: '存在正在上传的文件，请等待数据上传成功再试',
          type: 'warning'
        });
        return
      }
      switch (obj) {
        case "add":
          this.updateInfo = {};
          this.showWhich = obj;
          this.showDialog = true
          this.$nextTick(() => {
            this.$refs.addformRef.clearValidate();
          })
          break;
        case "edit":
          this.updateInfo = JSON.parse(JSON.stringify(row));
          this.showWhich = obj;
          this.showDialog = true
          this.$nextTick(() => {
            this.$refs.addformRef.clearValidate();
          })
          break;
        case "detail":
          this.updateInfo = JSON.parse(JSON.stringify(row));
          this.showWhich = obj;
          this.showDialog = true
          break;
        case "delete":
          this.deleteData(row.id);
          break;
        case "deleteMany":
          this.deleteManyData();
          break;
        case "export":
          this.exportTable();
          break;
        default:
          break;
      }
    },
    handleSubmitFile() {
      if (!this.updateInfo.uploadType && this.updateInfo.uploadType != 0) {
        this.$message({
          message: '上传类型不能为空',
          type: 'warning'
        });
        return
      }
      this.handleSubmit();
      // this.$refs.addformRef.validate((valid) => {
      //   if (valid) {
      //     this.handleSubmit();
      //   }
      // })
    },
    //提交事件
    async handleSubmit() {
      let _this = this;
      const fileDom = this.$refs.myFileControl
      if (fileDom && fileDom[0]) {
        this.uploading = true
        let fileList = await fileDom[0].uploadInfo(), propName = 'file'
        this.uploading = false
        if (!!fileList) {
          _this.updateInfo[propName + 'AddStr'] = JSON.stringify(fileList);   //去掉最后一个逗号避免后端报错，再加上中括号构造json字符串          
          _this.updateInfo['fileName'] = fileList[0].name;    //从上传的文件中读取文件名
        }
        if (fileDom[0]?.delFileList?.length > 0) {       // 将删除的图片由数组转为字符串拼接
          _this.updateInfo[propName + 'DelStr'] = JSON.stringify(fileDom[0].delFileList)
        }
      }
      if (!_this.updateInfo.fileName) {
        this.$message({
          message: '文件不能为空',
          type: 'warning'
        });
        return
      }
      switch (this.showWhich) {
        case 'add':
          this.addInfo();
          break;
        case 'edit':
          this.editInfo();
          break;
      }
    },
    addInfo() {
      let _this = this;
      this.method.addData(_this.updateInfo).then(function (response) {
        if (response.data.code == 0) {
          _this.getTableData();
          _this.showWhich = "";
          _this.showDialog = false
          _this.$notify({
            message: "信息保存成功！",
            type: "success",
            position: "bottom-right",
            duration: 2000,
          });
        }
      }).catch(function (error) {
        _this.$notify({
          message: "信息保存失败！",
          type: "error",
          position: "bottom-right",
          duration: 2000,
        });
        console.log(error)
      });
    },
    editInfo() {
      let _this = this;
      this.method.editData(_this.updateInfo).then(function (response) {
        if (response.data.code == 0) {
          _this.getTableData();
          _this.showWhich = "";
          _this.showDialog = false
          _this.$notify({
            message: "信息保存成功！",
            type: "success",
            position: "bottom-right",
            duration: 2000,
          });
        }
      }).catch(function (error) {
        _this.$notify({
          message: "信息保存失败！",
          type: "error",
          position: "bottom-right",
          duration: 2000,
        });
        console.log(error)
      });
    },
    deleteData(id) {
      this.$confirm("此操作将删除该项, 是否继续?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }).then(() => {
        let _this = this;
        _this.method.deleteData(id).then(function (response) {
          if (response.data.code == 0) {
            _this.getTableData();
            _this.showWhich = "";
            _this.showDialog = false
            _this.$notify({
              message: "信息删除成功！",
              type: "success",
              position: "bottom-right",
              duration: 2000,
            });
          }
        })
      })
    },
    deleteManyData() {
      let _this = this;
      if (_this.multipleSelection.length > 0) {
        _this.$confirm("此操作将删除该项, 是否继续?", "提示", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        }).then(() => {
          _this.method.deleteDatas(_this.multipleSelection).then(function (response) {
            if (response.data.code == 0) {
              _this.getTableData();
              _this.showWhich = "";
              _this.showDialog = false
              _this.$notify({
                message: "信息删除成功！",
                type: "success",
                position: "bottom-right",
                duration: 2000,
              });
            }
          })
        })
      } else {
        this.$notify({
          message: "请至少选择一项",
          type: "error",
          position: "bottom-right",
          duration: 2000,
        });
      }
    },
    closeDialog() {
      this.showDialog = false
    },
    exportTable() {
      this.exportLoading = true;
      let _this = this;

      if (this.tableAllData.length <= 0) {
        _this.$notify({
          message: "当前数据为空",
          type: "error",
          position: "bottom-right",
          duration: 1000,
        });
        this.exportLoading = false;
        return;
      }
      let filename = "" + dayjs().format("YYYY-MM-DD HH:ss:mm");
      let multiHeader = []; //标题设置
      let tHeader = [], filterVal = [];

      _this.tableItems.forEach(v => {
        tHeader.push(v.name);
        filterVal.push(v.prop);
      })
      let jsonData = this.tableAllData;
      let merges = []; // 合并单元格
      export_json_to_excel({
        multiHeader,
        header: tHeader,
        merges,
        filterVal,
        jsonData,
        filename: filename,
        autoWidth: 30,
        bookType: "xlsx",
      });
      this.exportLoading = false;
    },
  },
  activated() {
    let _this = this;
    _this.$nextTick(() => {

    })
  }
}
</script>
<style scoped lang="less">
.split-line {
  width: 100%;
  height: 1px;
  background-color: #eee;
  margin-bottom: 10px;
}

.predict-btn {
  background: #0066FF;
  color: #fff;
  width: 120px;
  line-height: 32px;
  text-align: center;
  font-size: 14px;
  cursor: pointer;
  border-radius: 0.2rem;
  margin: 0 auto;
}

.base-table {
  position: unset;
  height: calc(100% - 130px);
  overflow-y: auto;

  ul {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-start;
    background-color: #42424220;
    padding: 10px 20px;
    border-radius: 20px;
    margin-bottom: 16px;

    li {
      width: 33%;
      margin: 10px 0;
      display: flex;
      justify-content: center;

      span {
        color: #424242;
        font-weight: 600;
        width: 210px;
        display: flex;
        align-items: center;
        justify-content: flex-end;
      }

      .edit-input {
        width: 200px;
      }

      &:nth-of-type(3n) {
        margin-right: 0;
      }
    }
  }
}
</style>